/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			pgitlist.h
  \date			Sep 2012
  \author		TNick

  \brief		Contains the definition for PgItList class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef __PGITLIST_INC__
#define __PGITLIST_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<memtrack.h>
#include	<bytebuffer.h>
#include	<cpg/properties/iprop.h>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

namespace	cpg		{

class	PgItem;
class	PgSpace;

/**
*	@brief	represents a list of PgItem s
*/
class PgItList		: public MemTrack		{
	BBM_TRACK( PgItList );

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

private:

	/**
	*	@brief	internal list of items
	*/
	QList<PgItem *>			it_l;



	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:


	/**
	*	@brief	constructor;
	*/
	PgItList			( void ) : MemTrack()
	{ /* stub */ }



	/* ******************************************************************* */
	/** @name 	Querries on the list                                       */
	/* ******************************************************************* */
	///@{


	/**
	*	@brief	get the item at a particular index or NULL if out of bounds
	*/
	inline PgItem *		item			( int i ) const
	{
		if ( ( i < 0 ) || ( i >= it_l.count()) )
			return NULL;
		return it_l.at( i );
	}


	/**
	*	@brief	get the index of an item or -1 if not found
	*/
	inline int			indexOf			( PgItem * item ) const
	{ return it_l.indexOf( item ); }


	/**
	*	@brief	tell if a particular item is part of the list
	*/
	inline bool			contains		( PgItem * it ) const
	{ return it_l.contains( it ); }


	/**
	*	@brief	number of items that we store
	*/
	inline int			count			( void ) const
	{ return it_l.length(); }


	/**
	*	@brief	tell if we have some items inside
	*/
	inline bool			isEmpty			( void ) const
	{ return it_l.isEmpty(); }


	/**
	*	@brief	get'em all as a QList
	*/
	inline QList<PgItem *>	list		( void ) const
	{ return it_l; }


	///@}
	/* ******************************************************************* */



	/* ******************************************************************* */
	/** @name 	Modifies on the list                                       */
	/* ******************************************************************* */
	///@{


	/**
	*	@brief	add an item at the end of the list
	*/
	inline void			append			( PgItem * new_it )
	{
		Q_ASSERT( it_l.indexOf( new_it ) == -1 );
		it_l.append( new_it );
	}


	/**
	*	@brief	add an item at the end of the list
	*
	*	@return	the index where was found / inserted
	*/
	int					appendUnique	( PgItem * new_it );


	/**
	*	@brief	adds all items that are not already in this list from argument list
	*/
	void				appendUnique	( const PgItList & new_it );


	/**
	*	@brief	remove an item from the list
	*/
	inline void			removeOne		( PgItem * new_it )
	{ Q_ASSERT( it_l.contains( new_it ) ); it_l.removeOne( new_it ); }


	/**
	*	@brief	remove an item from the list
	*/
	bool				remove			( PgItem * new_it );


	/**
	*	@brief	remove an item from the list
	*/
	bool				remove			( int i );


	/**
	*	@brief	remove all items from the list
	*/
	inline void			clear			( void )
	{ it_l.clear(); }


	///@}
	/* ******************************************************************* */




	/* ******************************************************************* */
	/** @name 	Geometry of the items                                      */
	/* ******************************************************************* */
	///@{



	/**
	*	@brief	get the limits of the objects in this list
	*
	*	@return	false if the list is empty
	*/
	bool				extents			(
			ABOX2D &			r
			) const
	{ return boundingBox( r ); }


	/**
	*	@brief	return the box that bounds all items
	*
	*	@return false if there is no item
	*/
	bool				boundingBox			(
			ABOX2D &			r
			) const;


	/**
	*	@brief	return first item that intersects given rectangle
	*/
	PgItem *			itemAt			(
			const ABOX2D &		rct
			) const;


	/**
	*	@brief	translates all the items in the list by given ammount
	*/
	void				translate		(
			P2D &			displ
			);


	/**
	*	@brief	translates all the items in the list by given ammount
	*/
	void				translate		(
			qreal			dx,
			qreal			dy
			);


	/**
	*	@brief	rotates the items by given angle
	*/
	void				rotate		(
			P2D &			base,
			qreal			angle
			);


	/**
	*	@brief	scales all the items in the list
	*/
	void				scale			(
			P2D &			base,
			qreal			factor
			);


	///@}
	/* ******************************************************************* */



	/* ******************************************************************* */
	/** @name 	IProp like methods (we're not inheriting from it, tho)     */
	/* ******************************************************************* */
	///@{


	/**
	*	@brief	change a property using an index
	*/
	bool			setProp				(
			PropIndex				idx,
			const QString &			value
			);


	/**
	*	@brief	change a property using an index
	*/
	bool			setProp				(
			PropIndex				idx,
			qreal					value
			);


	/**
	*	@brief	change a property using an index
	*/
	bool			setProp				(
			PropIndex				idx,
			int						value
			);


	/**
	*	@brief	get the value for a property using an index
	*/
	QVariantList	getProp				(
			PropIndex				idx
			);


	///@}
	/* ******************************************************************* */



	/* ******************************************************************* */
	/** @name 	Various other methods                                      */
	/* ******************************************************************* */
	///@{


	/**
	*	@brief	remove all items and free the memory that they use
	*/
	void				deleteAll		( void );


	/**
	*	@brief	extracts the items from their respective container
	*/
	void				extract			( void );


	/**
	*	@brief	reinserts the items into their respective container
	*/
	void				insert			( void );


	/**
	*	@brief	return common space or NULL if different
	*/
	PgSpace *			space			( void );


	/**
	*	@brief	creates a new list with cloned objects
	*/
	void				clone				( PgItList & out ) const;


	/**
	*	@brief	tells if the two list have at least one common element
	*/
	bool				haveCommonItems		(
			const PgItList &	other
			) const;


	/**
	*	@brief	represent the list as XML
	*/
	void				asXML				(
			BBlocks::ByteBuffer *		root
			) const;


	///@}
	/* ******************************************************************* */


	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class PgItList	*/

/*  CLASS    =============================================================== */
//
//
//
//

}	//	namespace	cpg

#endif // __PGITLIST_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
